<template>
  <view v-if="isShow">
    <view
      @tap.stop.prevent
      @touchmove.stop.prevent
      class="wyb-popup-box"
      :style="{
        transitionDuration: duration + 'ms',
        opacity: contentOpacity || (type === 'center' ? 0 : 1),
        transform: contentTransform || autoTransform,
        zIndex: zIndex,
        borderTopRightRadius:
          type === 'center' || type === 'bottom' || type === 'left'
            ? radius + 'px'
            : 0,
        borderTopLeftRadius:
          type === 'center' || type === 'bottom' || type === 'right'
            ? radius + 'px'
            : 0,
        borderBottomRightRadius:
          type === 'center' || type === 'top' || type === 'left'
            ? radius + 'px'
            : 0,
        borderBottomLeftRadius:
          type === 'center' || type === 'top' || type === 'right'
            ? radius + 'px'
            : 0,
        width: autoWidth,
        height: autoHeight,
        minWidth: width + 'rpx',
        minHeight: height + 'rpx',
        top: sizeChange && type === 'center' ? winReTop : autoTop,
        bottom: autoBottom,
        left: autoLeft,
        right: autoRight,
        backgroundColor: bgColor,
      }"
    >
      <view
        class="wyb-popup-close"
        v-if="showCloseIcon"
        :style="{
          width: closeIcon ? closeIconSize + 'rpx' : 'auto',
          height: closeIcon ? closeIconSize + 'rpx' : 'auto',
          top:
            closeIconPos === 'top-right' || closeIconPos === 'top-left'
              ? vertOffset + 'rpx'
              : 'auto',
          bottom:
            closeIconPos === 'bottom-right' || closeIconPos === 'bottom-left'
              ? vertOffset + 'rpx'
              : 'auto',
          left:
            closeIconPos === 'bottom-left' || closeIconPos === 'top-left'
              ? horiOffset + 'rpx'
              : 'auto',
          right:
            closeIconPos === 'bottom-right' || closeIconPos === 'top-right'
              ? horiOffset + 'rpx'
              : 'auto',
        }"
      >
        <image
          class="wyb-popup-custom-close"
          v-if="showCloseIcon && closeIcon"
          :src="closeIcon"
          @tap="hide"
          :style="{
            width: closeIconSize + 'rpx',
            height: closeIconSize + 'rpx',
          }"
        />
        <view
          v-if="showCloseIcon && !closeIcon"
          class="iconfont icon-close"
          @tap="hide"
        />
      </view>

      <scroll-view
        class="wyb-popup-container"
        :style="{
          width: autoWidth,
          height: autoHeight,
        }"
        :enable-flex="true"
        :scroll-y="scrollY"
        :scroll-x="scrollX"
      >
        <view class="wyb-popup-slot">
          <view class="wyb-popup-title" v-if="title" :style="titleStyle">
            {{ title }}
          </view>
          <slot></slot>
        </view>
      </scroll-view>
    </view>
    <view
      class="wyb-popup-mask"
      @tap.stop="close"
      @touchmove.stop.prevent
      :style="{
        opacity: maskOpacity,
        transitionDuration: duration + 'ms',
        backgroundColor: 'rgba(0, 0, 0, ' + maskAlpha + ')',
        zIndex: zIndex - 1,
      }"
    />
  </view>
</template>

<script>
export default {
  data() {
    return {
      w: undefined,
      h: undefined,
      isShow: false,
      winReBottom: "",
      winReTop: "",
      sizeChange: false,
      contentOpacity: null,
      contentTransform: null,
      maskOpacity: 0,
      myStatusBarHeight: undefined,
      myWindowHeight: undefined,
    }
  },
  created() {
    let myGetSystemInfoSync = uni.getSystemInfoSync()
    this.w = myGetSystemInfoSync.screenWidth
    this.h = myGetSystemInfoSync.screenHeight
    this.myStatusBarHeight = myGetSystemInfoSync.statusBarHeight
    this.myWindowHeight = myGetSystemInfoSync.windowHeight
  },
  computed: {
    autoCenterTop() {
      let statusBarHeight = this.myStatusBarHeight
      let windowHeight = this.myWindowHeight
      let popupHeight = this.rpxToPx(this.height)
      let navHeight = 44
      let result = `${(windowHeight - popupHeight) / 2 - this.negativeTop}px`
      return result
    },
    autoTransform() {
      let result = ""
      switch (this.type) {
      case "center":
        if (this.centerAnim === "zoom-lessen") {
          result = `scale(${this.zoomLessenMulti})`
        } else if (this.centerAnim === "slide-up") {
          result = `translateY(${100 * this.slideMulti}%)`
        } else if (this.centerAnim === "slide-down") {
          result = `translateY(${-100 * this.slideMulti}%)`
        } else if (this.centerAnim === "fade") {
          result = "auto"
        }
        break
      case "bottom":
        result = "translateY(100%)"
        break
      case "top":
        result = "translateY(-100%)"
        break
      case "left":
        result = "translateX(-100%)"
        break
      case "right":
        result = "translateX(100%)"
        break
      }
      return result
    },
    autoWidth() {
      if (this.type === "center") {
        return `${this.width}rpx`
      } else {
        if (this.mode === "size-fixed") {
          if (this.type === "top" || this.type === "bottom") {
            return "100%"
          } else {
            return `${this.width}rpx`
          }
        } else {
          if (this.type === "top" || this.type === "bottom") {
            return "100%"
          } else {
            return "auto"
          }
        }
      }
    },
    autoHeight() {
      if (this.type === "center") {
        return `${this.height}rpx`
      } else {
        if (this.mode === "size-fixed") {
          if (this.type === "left" || this.type === "right") {
            return "100%"
          } else {
            return `${this.height}rpx`
          }
        } else {
          if (this.type === "left" || this.type === "right") {
            return "100%"
          } else {
            return "auto"
          }
        }
      }
    },
    autoTop() {
      if (this.type === "center") {
        return this.autoCenterTop
      } else if (this.type === "bottom") {
        return "auto"
      } else {
        return 0
      }
    },
    autoBottom() {
      if (this.type === "center" || this.type === "top") {
        return "auto"
      } else {
        return 0
      }
    },
    autoLeft() {
      if (this.type === "center") {
        return `${(this.w - this.rpxToPx(this.width)) / 2}px`
      } else if (this.type === "right") {
        return "auto"
      } else {
        return 0
      }
    },
    autoRight() {
      if (this.type === "center" || this.type === "left") {
        return "auto"
      } else {
        return 0
      }
    },
  },
  props: {
    type: {
      type: String,
      default: "bottom",
    },
    mode: {
      type: String,
      default: "size-auto",
    },
    title: {
      type: String,
      default: "",
    },
    height: {
      type: [String, Number],
      default: 400,
    },
    width: {
      type: [String, Number],
      default: 500,
    },
    radius: {
      type: [String, Number],
      default: 0,
    },
    zIndex: {
      type: [String, Number],
      default: 10076,
    },
    maskClickClose: {
      type: Boolean,
      default: true,
    },
    maskAlpha: {
      type: Number,
      default: 0.5,
    },
    duration: {
      type: Number,
      default: 400,
    },
    showCloseIcon: {
      type: Boolean,
      default: false,
    },
    scrollY: {
      type: Boolean,
      default: false,
    },
    scrollX: {
      type: Boolean,
      default: false,
    },
    closeIconPos: {
      type: String,
      default: "top-right",
    },
    closeIcon: {
      type: String,
      default: "",
    },
    closeIconSize: {
      type: [String, Number],
      default: "20",
    },
    vertOffset: {
      type: [String, Number],
      default: "22",
    },
    horiOffset: {
      type: [String, Number],
      default: "22",
    },
    centerAnim: {
      type: String,
      default: "zoom-lessen",
    },
    bgColor: {
      type: String,
      default: "#ffffff",
    },
    zoomLessenMulti: {
      type: Number,
      default: 1.15,
    },
    slideMulti: {
      type: Number,
      default: 1,
    },
    negativeTop: {
      type: Number,
      default: 0,
    },
    titleStyle: {
      type: Object,
      default: {},
    }, // 应用到标题上的样式对象
  },
  mounted() {
    // #ifdef H5
    let winHeight = this.myWindowHeight
    uni.onWindowResize((res) => {
      this.sizeChange = true
      if (this.type === "bottom") {
        this.winReBottom = winHeight - res.size.windowHeight + "px"
      } else if (this.type === "center") {
        this.winReTop =
          (res.size.windowHeight - this.rpxToPx(this.height)) / 2 -
          this.negativeTop +
          "px"
      }
    })
    // #endif
  },
  methods: {
    close() {
      this.maskClickClose && this.hide()
    },
    show() {
      this.isShow = true
      // #ifndef H5
      this.$nextTick(() => {
        this.maskIn()
        this.contentIn()
        this.wait(this.duration + 1).then(() => {
          this.$emit("show", {
            pageScroll: false,
            overflow: "hidden",
          })
        })
      })
      // #endif
      // #ifdef H5
      this.wait(10).then(() => {
        this.maskIn()
        this.contentIn()
        this.wait(this.duration + 1).then(() => {
          this.$emit("show", {
            pageScroll: false,
            overflow: "hidden",
          })
        })
      })
      // #endif
    },
    hide() {
      this.contentOut()
      this.maskOut()
      this.wait(this.duration + 1).then(() => {
        this.isShow = false
        this.$emit("hide", {
          pageScroll: true,
          overflow: "scroll",
        })
      })
    },
    contentIn() {
      switch (this.type) {
      case "center":
        if (this.centerAnim === "zoom-lessen") {
          this.contentOpacity = 1
          this.contentTransform = "scale(1)"
        } else if (
          this.centerAnim === "slide-up" ||
            this.centerAnim === "slide-down"
        ) {
          this.contentOpacity = 1
          this.contentTransform = "translateY(0)"
        } else if (this.centerAnim === "fade") {
          this.contentOpacity = 1
        }
        break
      case "bottom":
      case "top":
        this.contentTransform = "translateY(0)"
        break
      case "left":
      case "right":
        this.contentTransform = "translateX(0)"
        break
      }
    },
    contentOut() {
      this.contentOpacity = null
      this.contentTransform = null
    },
    maskIn() {
      this.maskOpacity = 1
    },
    maskOut() {
      this.maskOpacity = 0
    },
    rpxToPx(rpx) {
      return (rpx / 750) * this.w
    },
    wait(time) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve()
        }, time)
      })
    },
  },
}
</script>

<style lang="scss">
@import "./iconfont.css";
.wyb-popup-box {
  position: fixed;
  transition-timing-function: ease-out;
  transition-property: opacity, transform;
}

.wyb-popup-container {
  position: relative;
  box-sizing: border-box;
}

.wyb-popup-slot {
  width: 100%;
  height: 100%;

  .wyb-popup-title {
    font-size: 32rpx;
    font-weight: 500;
    color: #333333;
    text-align: center;
    margin-top: 30rpx;
  }
}

.wyb-popup-mask {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  transition-timing-function: ease;
  transition-property: opacity, transform;
}

.wyb-popup-close {
  position: absolute;
  // fontsize: 40rpx;
  color: #808080;
  z-index: 20000;
}

.wyb-popup-custom-close {
  left: 0;
  top: 0;
  position: absolute;
}
</style>
